package com.silong.swing.myWindows;

import javax.swing.*;
import javax.swing.undo.UndoManager;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

/**
 * Created by 龙哥 on 2022-01-17 15:38
 * Silong Software.
 * 列表框数据加载有三种方式：
 * 1）字符串数组
 * 2）Vector对象
 * 3）DefaultListModel对象
 */

public class ListFrame extends JFrame {

    JList<String> lstLeft; //列表框
    JList<String> lstRight; //目标列表框
    JButton btnSelect; //选择带走
    JButton btnSelectAll; //选择所有
    JButton btnUndo; //撤销
    JButton btnRedo; //重做
    UndoManager undoManager;
    JScrollPane jspSrc;//滚动条
    JScrollPane jspTarget;//滚动条
    JLabel lblInfo;//显示标题

    //创建数组，填充到 List
    //String[] leftData;
    //创建 Vector来进行List数据填充
    //Vector<String> rightData;
    //使用 ListModel进行数据填充
    DefaultListModel<String> listData;
    DefaultListModel<String> leftData;
    DefaultListModel<String> rightData;

    public ListFrame(){
        init();
    }

    private void init(){

        undoManager = new UndoManager();
        lblInfo = new JLabel("选择谁出征！");
        //声时 ListModel
        listData = new DefaultListModel<String>();
        listData.addElement("张飞");
        listData.addElement("关羽");
        listData.addElement("赵云");
        listData.addElement("马超");
        listData.addElement("黄忠");
        listData.addElement("刘备");
        listData.addElement("魏延");
        listData.addElement("司马超");

        //初始化数组
        //leftData = new String[]{"张飞","关羽","赵云","马超","黄忠","刘备"};
        //Vector只能一个一个添加
        rightData = new DefaultListModel<String>(); //实例化 ListModel
        //rightData = new Vector<String>();
        //rightData.add("张飞");
        //rightData.add("关羽");
        //rightData.add("赵云");
        //rightData.add("马超");
        //rightData.add("黄忠");
        //lstLeft = new JList<String>(leftData); //使用字符串进行数据注入
        lstLeft = new JList<String>(listData);  //使用DefaultListModel进行数据注入
        lstRight = new JList<String>(); //使用 Vector 进行数据注入
        //可以使用 setListData来设置列表框中数据
        //lstRight.setListData(leftData);
        //可以使用 setModel方法将 DefaultListModel来设置列表框数据
        //lstRight.setModel(listData);
        btnSelect = new JButton("带走"); //选择带走
        btnSelectAll = new JButton("全带"); //选择所有
        btnUndo = new JButton("撤销"); //撤消
        btnRedo = new JButton("重做"); //重做

        lblInfo.setSize(300,40);
        lblInfo.setLocation(50, 30);
        lblInfo.setFont(new Font("宋体", Font.PLAIN, 30));

        //创建滚动条
        jspSrc = new JScrollPane(lstLeft);
        jspSrc.setLocation(50,80);//设置滚动条后，不用设置大小与位置
        jspSrc.setSize(250,300);

        jspTarget = new JScrollPane(lstRight);
        jspTarget.setLocation(450,80);//设置滚动条后，不用设置大小与位置
        jspTarget.setSize(250,300);

        Container window = this.getContentPane();
        this.setSize(750, 550);
        this.setLocationRelativeTo(null); //距中
        this.setTitle("自定义控件大小位置");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //退出窗口关闭程序
        this.setBackground(Color.pink); //设置窗体背景
        //取消窗体装饰后，标题栏就没有了
        //this.setUndecorated(true); //先要进行 Undecorate才可以使用 Opacity
        //this.setOpacity(0.9f); //设置不透明 0.0f -1.0f
        //设置布局为空，优点:摆放灵活，缺点：代码量大，自适应能力差。
        this.setLayout(null);

        //自定义列表框的位置 ，大小
        //txaSrc.setLocation(50,50);//设置滚动条后，不用设置大小与位置
        //txaSrc.setSize(300,300);
        lstLeft.setFont(new Font("宋体", Font.BOLD, 25));
        //设置文本框的边框，颜色与宽度
        lstLeft.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
        //添加 Key监听 Ctrl+Z
        lstLeft.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //判断是否为 Ctrl + Z
                if(e.isControlDown() && e.getKeyCode()== KeyEvent.VK_Z){
                    //判断是否可以撤销
                    if(undoManager.canUndo()){
                        undoManager.undo();
                    }
                }
                //判断重做 Ctrl + Y
                if(e.isControlDown() && e.getKeyCode() == KeyEvent.VK_Y){
                    //判断是否可以重做
                    if(undoManager.canRedo()){
                        undoManager.redo();
                    }
                }
            }
        });

        //txaTarget.setLocation(380,50);//设置滚动条后，不用设置大小与位置
        //txaTarget.setSize(300,300);
        lstRight.setFont(new Font("宋体", Font.BOLD, 25));
        lstRight.setBorder(BorderFactory.createLineBorder(Color.GRAY,1));
        //给文本域添加撤销与重做
        lstRight.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //判断是否为 Ctrl + Z
                if(e.isControlDown() && e.getKeyCode()== KeyEvent.VK_Z){
                    //判断是否可以撤销
                    if(undoManager.canUndo()){
                        undoManager.undo();
                    }
                }
                //判断重做 Ctrl + Y
                if(e.isControlDown() && e.getKeyCode() == KeyEvent.VK_Y){
                    //判断是否可以重做
                    if(undoManager.canRedo()){
                        undoManager.redo();
                    }
                }
            }
        });

        //设置按钮大小及字体
        btnSelect.setSize(100,40);
        btnSelect.setLocation(320, 100);
        btnSelect.setFont(new Font("宋体", Font.PLAIN, 20));
        btnSelect.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //带走谁，只能从后面往前面走，这样，索引就不会变
                int[] idx = lstLeft.getSelectedIndices();
                for (int i = idx.length -1 ; i >= 0 ; i--) {
                    //添加要删除的原数到右边列表框中
                    //String elementAt = (String) listData.getElementAt(idx[i]);
                    //addElement是每次添加到最后面
                    //rightData.addElement(listData.remove(idx[i]));
                    int index = rightData.size();
                    rightData.insertElementAt(listData.remove(idx[i]), index);
                    //移走 DefaultListModel中数组
                    //listData.remove(idx[i]);
                }
                lstRight.setModel(rightData);
            }
        });

        btnSelectAll.setSize(100,40);
        btnSelectAll.setLocation(320, 150);
        btnSelectAll.setFont(new Font("宋体", Font.PLAIN, 20));
        btnSelectAll.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //选择所有项目到右边框
                int index = rightData.size();
                for (int i = listData.size() -1 ; i >= 0 ; i--) {
                    rightData.insertElementAt(listData.remove(i), index);
                }
                lstRight.setModel(rightData);
            }
        });

        btnUndo.setSize(100,40);
        btnUndo.setLocation(320, 200);
        btnUndo.setFont(new Font("宋体", Font.PLAIN, 20));
        btnUndo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //撤销
                int[] idx = lstRight.getSelectedIndices();
                for (int i = idx.length -1 ; i >= 0 ; i--) {
                    int index = listData.size();
                    listData.insertElementAt(rightData.remove(idx[i]), index);
                }
                lstLeft.setModel(listData);
            }
        });

        btnRedo.setSize(100,40);
        btnRedo.setLocation(320, 250);
        btnRedo.setFont(new Font("宋体", Font.PLAIN, 20));
        btnRedo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //重做，清空右边列表，装到左边
                for (int i = rightData.size() - 1 ; i >= 0 ; i--) {
                    int index = listData.size();
                    listData.insertElementAt(rightData.remove(i), index);
                }
                lstLeft.setModel(listData);
            }
        });

        //通过列表的双击来处理数据移动
        lstLeft.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                //双击事件
                if(e.getClickCount() == 2){
                    int index = lstLeft.getSelectedIndex(); //左边用户双击的数据索引
                    int indexEnd = rightData.size(); //右边列表已经有的数据条数
                    rightData.insertElementAt(listData.remove(index), indexEnd);
                }
                lstRight.setModel(rightData);
            }
        });

        lstRight.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                //双击事件
                if(e.getClickCount() == 2){
                    int index = lstRight.getSelectedIndex(); //右边用户双击的数据索引
                    int indexEnd = listData.size(); //左边列表已经有的数据条数
                    listData.insertElementAt(rightData.remove(index), indexEnd);
                }
                lstLeft.setModel(listData);
            }
        });

        //在窗体上加载列表框 //将滚动条加入
        window.add(jspSrc);
        window.add(jspTarget);
        //window.add(txaSrc); //如果使用滚动条后，这个不要使用
        //window.add(txaTarget); //如果使用滚动条后，这个不要使用
        window.add(btnSelect);
        window.add(btnSelectAll);
        window.add(btnUndo);
        window.add(btnRedo);
        window.add(lblInfo);
    }

    public static void main(String[] args) {
        ListFrame textFrame = new ListFrame();
        textFrame.setVisible(true);
    }
}
